package com.freeheart.aop.log.logscan;

import com.freeheart.aop.log.log.Log;
import com.freeheart.aop.log.log.LogIgnore;
import com.freeheart.aop.log.LogInterceptor;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
 * 针对@LogScan注解设计的日志增强的Advice（横切逻辑）
 * <p/>
 * <p>
 * Advisor/Aspect：封装Advice和Pointcut的类，将它交给AOP框架，AOP框架会自动代理这些方法
 * </p>
 * <p>Advice：增强的逻辑</p>
 * <p>Pointcut：对那些方法进行增强，可用切点表达式、方法名、正则表达式进行匹配</p>
 */
public class LogScanAdvice implements MethodInterceptor {

    private final Logger logger = LoggerFactory.getLogger(LogScanAdvice.class);
    /**
     * 可具体扩展的日志增强逻辑
     */
    public final LogInterceptor logInterceptor;

    public LogScanAdvice(LogInterceptor logInterceptor) {
        this.logInterceptor = logInterceptor;
    }


    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // 为了避免重复，有这些注解时，让LogScan失效就行
        if (invocation.getMethod().isAnnotationPresent(Log.class) ||
                invocation.getMethod().isAnnotationPresent(LogIgnore.class) ||
                invocation.getMethod().getDeclaringClass().isAnnotationPresent(Log.class) ||
                invocation.getMethod().getDeclaringClass().isAnnotationPresent(LogIgnore.class)
        ) {
            return invocation.proceed();
        }

        Object[] arguments = invocation.getArguments();
        Method method = invocation.getMethod();

        return logInterceptor.process(method, arguments, () -> {
            try {
                return invocation.proceed();
            } catch (Throwable throwable) {
                logger.warn("切面异常", throwable);
                return new Exception("切面异常");
            }
        });

    }
}
